iT邦幫忙

2026 iThome 鐵人賽

DAY 25
0
Claude AI

AI 負責答,我負責讓答案可信——公部門工程師的 30 天 Claude 協作紀律系列 第 25 篇

Day 25:我讓工具來審我的「專案憲法」,它信心最高的那筆,判斷錯了

  • 分享至 

  • xImage
  •  

Day 25:我讓工具來審我的「專案憲法」,它信心最高的那筆,判斷錯了

昨天講怎麼寫一份「專案憲法」,今天講怎麼維護它。因為一份用了很久的規範,一定會長雜草——當初有道理的規則,環境變了就過期;隨手加的強調,堆著堆著變雜訊;有些內容其實 AI 讀一下程式碼就知道,根本不必寫進常駐規範白佔額度。問題是,這些雜草很難靠肉眼一條條看出來。

引子是一則官方說法:換到 Opus 5.5 之後,建議先做一件事——審查你的提示詞。因為很多提示是為舊模型寫的,在新模型上會變成負擔,讓它輸出更多、重複呼叫工具,額度就這樣燒掉。做法是在 Claude Code 裡跑一個叫 prompt-audit 的指令,它會掃你的 skills、CLAUDE.md、還有呼叫 API 的程式碼。官方還附了數據:拿 44 張客服單做基準,換模型先省約 18%,再跑一次 audit 又省 9%,合計比原本便宜約 25%。

聽起來很動人,但我第一個動作不是照做,是查證。查下來大致屬實,出處是官方部落格九月的文章,指令和那組省錢數據都對得上。只是「官方建議先做這件事」講得太重了——它其實只是文章眾多省錢建議中的一條,官方自己還特別說這數字只來自單一基準,該當範例看、不是預期值。再權威的來源,先查了再信,這是這系列一貫的姿態;但這則說法值得一試,於是我真的跑了一遍。以下是結果,跟我原本以為的很不一樣。

先分清楚:這跟原本就有的 /doctor 是同一件事嗎

我的第一個疑問是:Claude Code 本來就有個 /doctor 在做健檢,這兩個不是重複了?查清楚後發現,它們問的是不同的問題。

/doctor 管的是「這條規則需不需要存在」——有沒有重複、根本沒在用、或是 AI 自己就能從程式碼推斷出來、不必寫。prompt-audit 管的是「這條規則的寫法會不會讓新模型多做事」——像「每次都要驗證兩次」這種儀式、「CRITICAL: YOU MUST」這種過度強調、或自相矛盾的指令。一條規則可以通過 /doctor(不重複、有在用),卻仍被 prompt-audit 抓出來。兩個都跑不衝突:先用 /doctor 清掉多餘的,再用 prompt-audit 修剩下的寫法。

我先跑了 /doctor。結果整體健康,只抓到三個一個月沒用過的擴充、還有一份 458 MB 的舊版執行檔備份佔著空間——清掉無妨。

真正值得記的是中間插進來的一段。我順手要求它,把一條「看截圖」的規則改成「用到時才載入」,想省點常駐 token。AI 沒有照做,反而踩了我剎車。 它的理由有兩層:一是這條規則的觸發點是「我說的一句話」(我說「去看截圖 001」),不是某個檔案,改成延遲載入之後,需要它的時候反而不會被載入;二是這條規則裡有一句安全限制——「刪除只限某個暫存資料夾,禁止刪其他路徑的任何檔案」——這種「禁止做某事」的護欄必須一直常駐,一旦收進延遲載入,我哪天換個說法沒觸發到,就等於沒有保護。為了省那大約五十個 token,把一條安全護欄變得不可靠,不划算。

這又是一次雙向把關:我以為在做優化,AI 看出這個「優化」會拆掉一道安全網,於是攔了下來。(順帶一提,昨天我從方法論裡拿掉的「少用強調語氣」那個原則,其實正屬於這一關——官方談 CLAUDE.md 寫法時提醒過,「一律」「CRITICAL」這類過度強調對新模型是負擔,prompt-audit 專門會抓;那是調校的事,不是寫憲法的本體,放這裡才對。)

那,真正「絕對不能做」的事,靠什麼擋?

上面那條被 AI 守住的刪除限制,其實還是寫在 CLAUDE.md 裡——也就是說,昨天那句話在這裡又成立了一次:它終究只是強預設,模型理論上仍可能失手。 那如果我要的是「絕對不准刪專案資料夾外的任何檔案」「絕對不准執行某類外部指令」這種一次都不能出錯的鐵律,該放哪?

我後來認真查過 Claude Code 的權限機制,才發現「絕對」這件事比想像中稀有。它的自動核准模式底下有一份預設規則清單,粗分三層:一小批直接放行的(唯讀、工作目錄內的編輯這類),一大批預設封鎖的(幾十條,像 force push、刪雲端資料、對外送敏感資訊),還有——這是關鍵——真正不可解除的硬封鎖只有一條:把敏感資料送出信任邊界。其餘那幾十條「封鎖」其實都是軟的:它擋你一下,但只要你在對話裡明確講清楚「要做什麼、對象是誰」,封鎖就解除。設計上就預期你會遇到「被擋 → 補一句話放行」的循環。

這裡藏著一個對「規範效力」很重要的體悟:連對話裡臨時講的界線,也是軟的。 你說一句「先別 push、等我 review」,它確實會擋住相符的動作——但這條界線不是被存成規則,而是分類器每次都從當前對話重讀出來的。也就是說,一旦對話被壓縮、那句話被摘要掉,界線就跟著消失了。對一個要「永遠成立」的禁令來說,這太脆弱。

所以真正擋得住、又不怕被對話沖走的,只有寫進設定檔的 deny 規則(或 hook)——它由程式在每一次工具呼叫之前檢查,不管對話裡有沒有那句話、模型記不記得,都一樣執行。對應我前面舉的兩個例子:「禁止某類外部指令」用 deny 規則(按指令樣式比對)擋;「禁止刪除專案外的檔案」則適合 hook,因為它要判斷路徑,是樣式比對做不到的。

而 /doctor 在這整件事裡的角色,不是「做安全調整」,是把這層設定攤出來檢查給我看:它指出我的允許清單有幾條開太寬(git push *、curl * 這種幾乎全開的),還有六條多餘、已被涵蓋。它自己不動手,是我看過之後另外請它把允許清單從十六條收到十條。順帶一提,我查自己的信任邊界設定時,發現幾乎整份是空的——這代表除了當前這個專案,其他東西預設都在信任範圍外,動到專案外(例如 ~/.claude/ 底下)就會被多問一次。那不是誤判,是它不曉得那是我自己的機器。

一路查下來,「維護憲法」其實是分層的:CLAUDE.md 管「大多數時候都照我的判斷走」,快而有彈性;deny 規則和 hook 管「這幾件事絕對不能出錯」,確定但要一條條設。把一條「絕對禁令」只寫在 CLAUDE.md、甚至只在對話裡交代,等於把鐵律降級成了建議。 該當鐵律的,就得放到擋得住、又不會被對話沖走的那一層去。

真正的審查:那個被吹上天的省錢賣點,在我身上是 0 筆

清完多餘的,我對全域設定跑了 prompt-audit(它預設只看目前專案,要審個人全域設定得多加一個路徑參數——全域那份其實更該審,因為它會載入到每一個專案的每一個 session)。

報告第一句就很有意思:官方那個要抓的「為舊模型寫、現在過時」的儀式性提示,在我的設定裡是 0 筆。 它的原話是「整體寫得不錯,語氣強調很少,大部分內容是只有你知道的專案慣例和背景,這些本來就該留著」。

我把這件事講白,是因為它很公道:官方沒有騙人,那套反模式確實存在、確實值得清。但那個「換模型先審提示詞、再省 9%」的賣點,對一份平常就在維護、沒讓儀式指令囤積的憲法來說,能省的是 0。 會從中大幅獲利的,是那些從更舊模型一路複製、堆滿「務必」「一律」「驗證兩次」卻很久沒回頭看的設定。這反過來說明了昨天那件事:憲法的價值不在寫了多少條,而在有沒有持續汰換。

但它沒白跑——抓到了四個真 bug

有意思的地方在這裡:審查沒白跑,只是它抓到的東西,跟它宣稱要抓的完全是兩回事。它沒找到半條過時規則,卻揪出四個「AI 會照著做、但做了會出錯」的事實錯誤。其中兩個影響最大:

第一,一個叫 merge 的 skill,它的「語法驗證」步驟其實等於沒在驗。它在把我的分支合併進主線之後,才去比對兩者的差異——但合併完,兩邊內容早就一樣了,差異清單永遠是空的,所以每次報告「0 個錯誤」都不是真的驗過。

第二,一個叫 publish 的 skill,發佈路徑寫成 WSL 的格式(/mnt/d/...),但我實際用的是 Git Bash,路徑該是 /d/...。這條最危險,因為錯的路徑後面就接著一個 rm -rf。報告還補了一句:從過去的對話紀錄看,AI 每次執行時其實都自己臨時改成對的路徑才跑成功——也就是說這個錯誤一直在,只是每次被現場繞過,從沒被寫回檔案。

這一段是「知識可以外包」最標準的示範:把十幾個設定檔逐條掃過、比對出哪裡跟實際環境對不上,這種系統性的體力活,交給工具又快又整齊,我自己沒耐心一條條看。

但信心最高的那一筆,它判斷錯了——錯在它拿不到的東西

報告把 merge 那筆的信心標成「高」。但它錯了。

它說 merge 的驗證「等於沒在驗證」,這個結論的前提是「合併後比對沒有意義」。可是它不知道這個 skill 當初的設計用意:我這個流程有兩個前提——主線和我自己的分支各自都已經驗證過,所以合併時真正要確認的,只有「合併這個動作本身有沒有把東西弄壞」。在這個前提下,只有兩邊都改過、被 git 自動合在一起的檔案才有風險,而合併後比對差異,剛好涵蓋這些檔案。它的寫法其實是對的。

我把這個前提補給它,它立刻撤回:「你說得對,我撤回第 1 筆……我先前說它『等於沒在驗證』,是沒弄清楚設計用意就下的結論。」

這正好是昨天那件事的活證據。 昨天我說「沒寫下原因的規則,遲早會被誤判」——而這個 merge skill 就是我當初只寫了做法、沒把設計前提寫進去的那一條。結果一個信心標成「高」的工具,就據此判它「等於沒在做事」、建議我改掉。差一點,一個本來正確的機制就被我照著「修正」改壞了。AI 能看出「這段程式碼的行為是什麼」,卻看不出「它當初為什麼要這樣設計」——因為那個「為什麼」不在程式碼裡,是我漏寫的。

最漂亮的一段:它撤回時又提了新疑點,我沒照收,它就真的跑一次證明給我看

故事到這還沒完,而接下來這一段,是我覺得整篇最值得寫的。

AI 撤回那筆之後,不是就閉嘴了。它順著同一個邏輯,主動提了一個新的邊界情況:如果主線那邊刪掉了某個檔案、而我的分支還留著它,這個檔案會出現在差異清單裡,但合併後它已從磁碟消失,驗證指令去讀一個不存在的檔案就會報錯,變成誤報。

換成以前,我可能就信了。但這次我沒有照單接受,反而挑戰它的邏輯:這狀況真的會成立嗎?主線刪掉、我沒刪,合併後那個檔案不是本來就該被刪掉嗎?就算沒被刪,它也已經脫離 git 管控了,怎麼還會影響到驗證?

AI 的回應方式,是這整篇最值得學的地方——它沒有嘴硬、也沒有繼續用推論跟我辯,而是說「我在暫存資料夾建一個測試用的 repo,把這個情況實際跑一次確認」。 它真的建了一個小 repo,讓主線刪掉一個檔、分支保留它,合併,然後一步步驗給我看:合併後那個檔案確實從磁碟消失了;但差異清單仍然列著它——因為那份清單來自 git 的提交紀錄,而驗證指令是去讀磁碟,兩邊依據不同、對不上,就產生誤報。跑完它還補了一句:我直覺的第一點(合併後檔案會被刪)是對的,而誤報也真的因此成立。確認完,它把那個暫存 repo 刪掉。

我特別看重這一段,是因為它把「協作」推到了一個更好的狀態:不是誰用嘴說服誰,而是拿證據。 我提出的質疑,逼它把一個「聽起來合理」的推論,變成一個「實際跑過、確認成立」的結論。AI 在這裡的價值,不是「它早就知道答案」——它一開始也只是推論——而是它願意、也有能力去建一個受控的小實驗把事情跑一遍,而不是停在嘴上。這比它直接給我一個正確答案還可貴,因為我看得到那個答案是怎麼被驗出來的。

這一天的分工

維護憲法這件事,結果跟資安篇是同一條線,只是換了層次:你可以把「檢查規範」交給工具,但不能把「這條規則到底對不對、當初為什麼這樣寫」的判斷一起交出去。

工具(連同 AI)在這篇做的,是它最擅長的:把十幾個設定檔逐條掃過、比對出哪裡跟實際環境對不上、甚至願意建個暫存 repo 把邊界情況實際跑一次。這些是體力活與系統性驗證,我外包得很放心。但三個真正的判斷都留在我這邊:一是設計意圖——只有我知道 merge 那個流程的前提,工具少了這塊,信心再高也會判錯;二是該不該接受它的新結論——它撤回後提的那個誤報疑點,我沒有照單全收,我的質疑才逼出後來那次實測;三是那個省錢賣點值不值得追——審完才知道對我是 0 筆,這件事沒有人能先告訴我,是我自己跑過才有的答案。

而這一整輪最實在的收穫,是回到昨天那句話:那條被誤判的 merge 規則,我事後做的第一件事,就是把當初漏寫的兩個設計前提,補寫回它的 skill 裡。這樣下一次——不管是別的工具、還是另一個 AI session——再讀到它,就不會在同一個地方誤判了。 憲法的維護,維護的從來不只是規則本身,是規則背後那個「為什麼」的完整度。

明天換一個範圍。憲法管的是「一個專案內」的判斷,但我有些判斷是跨專案的——哪個共用模組搬到哪、哪個功能在哪些專案已經上線、有哪些跨專案的坑還沒補。這種東西放在某一個專案的 CLAUDE.md 裡不夠,因為別的專案的 session 讀不到。所以我把它放到一個所有專案、所有對話都能讀寫的地方。明天談這個。


上一篇
Day 24:我的「專案憲法」——每一條留得下來的規則,背後都有一次教訓
下一篇
Day 26:AI 每一次都是一張白紙——所以我給它一塊跨專案的共用記憶
系列文
AI 負責答,我負責讓答案可信——公部門工程師的 30 天 Claude 協作紀律 共 26 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言